package com.photoeditor.demo.util.hook;

import android.os.Build;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by @author winn on 18/7/24.
 */

public class ActivityManagerHook implements InvocationHandler {

    private Object mOrigin;

    ActivityManagerHook(Object origin) {
        this.mOrigin = origin;
    }

    public Object getOrigin() {
        return mOrigin;
    }

    public static boolean hookActivityManagerNative() {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // 线上9.0系统crash，先不hook
                if (Build.VERSION.SDK_INT >= 28) {
                    return false;
                }
                return hookAMSForAndroidO();
            } else {
                ClassLoader loader = ClassLoader.getSystemClassLoader();
                Field singletonField = ReflectUtils.findField(loader.loadClass("android.app.ActivityManagerNative"), "gDefault");
                ReflectUtils.ReflectObject singletonObjWrap = ReflectUtils.wrap(singletonField.get(null));
                Object realActivityManager = singletonObjWrap.getChildField("mInstance").get();
                Object fakeActivityManager = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
                        new Class[]{loader.loadClass("android.app.IActivityManager")},
                        new ActivityManagerHook(realActivityManager));
                singletonObjWrap.setChildField("mInstance", fakeActivityManager);
                return true;
            }
        } catch (Throwable e) {
            e.printStackTrace();
            return false;
        }
    }

    private static boolean hookAMSForAndroidO() {
        boolean ret = false;
        try {
            Class activityManagerNativeClass = Class.forName("android.app.ActivityManager");
            Field getDefault = activityManagerNativeClass.getDeclaredField("IActivityManagerSingleton");
            getDefault.setAccessible(true);
            Object IActivityManagerSingleton = getDefault.get(null);
            Class<?> singleton = Class.forName("android.util.Singleton");
            Field mInstanceField = singleton.getDeclaredField("mInstance");
            mInstanceField.setAccessible(true);
            //gDefault单例对象里面的mInstance值
            Object rawIActivityManager = mInstanceField.get(IActivityManagerSingleton);

            Class IActivityManagerClass = Class.forName("android.app.IActivityManager");
            Object hookOActivityManager = Proxy.newProxyInstance(IActivityManagerClass.getClassLoader(),
                    new Class[]{IActivityManagerClass}, new ActivityManagerHook(rawIActivityManager));
            mInstanceField.set(IActivityManagerSingleton,hookOActivityManager);
            ret = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        switch (method.getName()) {
            //ActivityManagerNative.getDefault().activityStopped(activity.token, state, persistentState, description);
            case "activityStopped": {
                try {
                    return method.invoke(getOrigin(), args);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
            default:
                break;
        }
        return method.invoke(getOrigin(), args);
    }
}
